package tasks.io.core;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tasks.io.client.TioClientConfig;
import tasks.io.core.lock.MapWithLock;
import tasks.io.core.lock.SetWithLock;
import tasks.io.core.prop.MapWithLockPropSupport;
import tasks.io.core.stat.GroupStat;
import tasks.io.core.task.CloseTask;
import tasks.io.core.thread.SynThreadPoolExecutor;
import tasks.io.server.TioServerConfig;

import java.nio.ByteOrder;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;


public abstract class TioConfig extends MapWithLockPropSupport {
    static Logger log = LoggerFactory.getLogger(TioConfig.class);
    /**
     * 默认的接收数据的buffer size
     */
    public static final int READ_BUFFER_SIZE = Integer.getInteger("tio.default.read.buffer.size", 20480);
    private final static AtomicInteger ID_ATOMIC = new AtomicInteger();
    public Map<String, ClientNodes> ids;
    private ByteOrder byteOrder = ByteOrder.BIG_ENDIAN;
    public boolean isShortConnection = false;

    public boolean debug = false;
    public GroupStat groupStat = null;
    public boolean statOn = true;
    public PacketConverter packetConverter = null;
    /**
     * 本jvm中所有的TioServerConfig对象
     */
    public static final Set<TioServerConfig> ALL_SERVER_GROUPCONTEXTS = new HashSet<>();
    /**
     * 本jvm中所有的TioClientConfig对象
     */
    public static final Set<TioClientConfig> ALL_CLIENT_GROUPCONTEXTS = new HashSet<>();
    /**
     * 本jvm中所有的TioConfig对象
     */
    public static final Set<TioConfig> ALL_GROUPCONTEXTS = new HashSet<>();
    /**
     * 启动时间
     */
    public long startTime = SystemTimer.currTime;
    /**
     * 是否用队列发送
     */
    public boolean useQueueSend = true;

    /**
     * 心跳超时时间(单位: 毫秒)，如果用户不希望框架层面做心跳相关工作，请把此值设为0或负数
     */
    public long heartbeatTimeout = 1000 * 120;
    /**
     * 解码出现异常时，是否打印异常日志
     */
    public boolean logWhenDecodeError = false;

    /**
     * 接收数据的buffer size
     */
    private int readBufferSize = READ_BUFFER_SIZE;
    private GroupListener groupListener = null;

    public SynThreadPoolExecutor tioExecutor = null;
    public CloseTask closeRunnable;
    public ThreadPoolExecutor groupExecutor = null;
    public ClientNodes clientNodes = new ClientNodes();
    public SetWithLock<ChannelContext> connections = new SetWithLock<ChannelContext>(new HashSet<ChannelContext>());


    protected String id;

    protected String name = "未命名";

    private boolean isStopped = false;

    public MapWithLock<Integer, Packet> waitingResps = new MapWithLock<Integer, Packet>(new HashMap<Integer, Packet>());

    public TioConfig() {
        this(null, null);
    }

    /**
     * @param tioExecutor
     * @param groupExecutor
     * @author: tanyaowu
     */
    public TioConfig(SynThreadPoolExecutor tioExecutor, ThreadPoolExecutor groupExecutor) {
        super();
        ALL_GROUPCONTEXTS.add(this);
        if (this instanceof TioServerConfig) {
            ALL_SERVER_GROUPCONTEXTS.add((TioServerConfig) this);
        } else {
            ALL_CLIENT_GROUPCONTEXTS.add((TioClientConfig) this);
        }

        if (ALL_GROUPCONTEXTS.size() > 20) {
            log.warn("已经产生{}个TioConfig对象，t-io作者怀疑你在误用t-io", ALL_GROUPCONTEXTS.size());
        }
        this.id = ID_ATOMIC.incrementAndGet() + "";

        this.tioExecutor = tioExecutor;
        if (this.tioExecutor == null) {
            this.tioExecutor = Threads.getTioExecutor();
        }

        this.groupExecutor = groupExecutor;
        if (this.groupExecutor == null) {
            this.groupExecutor = Threads.getGroupExecutor();
        }

        closeRunnable = new CloseTask(this.tioExecutor);
    }


    /**
     * 获取TioHandler对象
     *
     * @return
     * @author: tanyaowu
     */
    public abstract TioHandler getTioHandler();

    /**
     * 获取TioListener对象
     *
     * @return
     * @author: tanyaowu
     */
    public abstract TioListener getTioListener();

    /**
     * @return
     * @author tanyaowu
     */
    public ByteOrder getByteOrder() {
        return byteOrder;
    }

    /**
     * @return the groupListener
     */
    public GroupListener getGroupListener() {
        return groupListener;
    }


    /**
     * @return
     * @author tanyaowu
     */
    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }


    /**
     * @return the syns
     */
    public MapWithLock<Integer, Packet> getWaitingResps() {
        return waitingResps;
    }


    /**
     * @return the isStop
     */
    public boolean isStopped() {
        return isStopped;
    }

    /**
     * @param byteOrder
     * @author tanyaowu
     */
    public void setByteOrder(ByteOrder byteOrder) {
        this.byteOrder = byteOrder;
    }

    /**
     * @param isEncodeCareWithChannelContext the isEncodeCareWithChannelContext to set
     */
    //	public void setEncodeCareWithChannelContext(boolean isEncodeCareWithChannelContext) {
    //		this.isEncodeCareWithChannelContext = isEncodeCareWithChannelContext;
    //	}

    /**
     * @param groupListener the groupListener to set
     */
    public void setGroupListener(GroupListener groupListener) {
        this.groupListener = groupListener;
    }

    /**
     * @param heartbeatTimeout the heartbeatTimeout to set
     */
    public void setHeartbeatTimeout(long heartbeatTimeout) {
        this.heartbeatTimeout = heartbeatTimeout;
    }

    public void setName(String name) {
        this.name = name;
    }


    /**
     * @param readBufferSize the readBufferSize to set
     */
    public void setReadBufferSize(int readBufferSize) {
        this.readBufferSize = Math.min(readBufferSize, TcpConst.MAX_DATA_LENGTH);
    }

    /**
     * @param isShortConnection the isShortConnection to set
     */
    public void setShortConnection(boolean isShortConnection) {
        this.isShortConnection = isShortConnection;
    }

    /**
     * @param isStopped the isStop to set
     */
    public void setStopped(boolean isStopped) {
        this.isStopped = isStopped;
    }


    public GroupStat getGroupStat() {
        return groupStat;
    }


    /**
     * 是否用队列发送，可以随时切换
     *
     * @param useQueueSend
     * @author tanyaowu
     */
    public void setUseQueueSend(boolean useQueueSend) {
        this.useQueueSend = useQueueSend;
    }

    /**
     * 是服务器端还是客户端
     *
     * @return
     * @author tanyaowu
     */
    public abstract boolean isServer();

    public int getReadBufferSize() {
        return readBufferSize;
    }


}
